package com.lap.service.starter.tools;

import java.net.*;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;

/**
 * 获取本机系统
 *
 * @author Shuisheng Lao(劳水生)
 * @version 0.0.1
 */
@Slf4j
public final class LocalIpUtil {

  private LocalIpUtil() {}

  public static InetAddress getAddress() {
    return findFirstValidNetworkAddress().orElseGet(LocalIpUtil::getFallbackLocalAddress);
  }

  private static Optional<InetAddress> findFirstValidNetworkAddress() {
    try {
      Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
      while (interfaces.hasMoreElements()) {
        NetworkInterface ni = interfaces.nextElement();
        if (isUsableInterface(ni)) {
          for (InetAddress address : Collections.list(ni.getInetAddresses())) {
            if (isUsableAddress(address)) {
              return Optional.of(address);
            }
          }
        }
      }
    } catch (SocketException e) {
      log.warn("Unable to get network interfaces: {}", e.getMessage());
    }
    return Optional.empty();
  }

  private static boolean isUsableInterface(NetworkInterface ni) throws SocketException {
    String name = ni.getName();
    return ni.isUp()
        && !ni.isLoopback()
        && !ni.isVirtual()
        && !ni.isPointToPoint()
        && (name.startsWith("eth") || name.startsWith("ens") || name.startsWith("wlan0"))
        && !name.toLowerCase().contains("virtual");
  }

  private static boolean isUsableAddress(InetAddress address) {
    return address instanceof Inet4Address && !address.isLoopbackAddress();
  }

  private static InetAddress getFallbackLocalAddress() {
    try {
      return InetAddress.getLocalHost();
    } catch (UnknownHostException e) {
      log.warn("Fallback to getLocalHost failed: {}", e.getMessage());
      return null;
    }
  }
}
